package com.sumainfor.common.wechat;

import com.sumainfor.common.config.LockUtil;
import com.sumainfor.common.config.RedisUtils;
import com.sumainfor.common.exception.TCException;
import lombok.extern.log4j.Log4j2;
import net.sf.json.JSONObject;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Author Eddy·Chen
 * @Email 835033913@qq.com
 * @Create 2019-06-10 20:42
 */
@Log4j2
public class WxUtil {


    @Autowired
    private RedisUtils redisUtils;

    public static final String ACCESS_TOKEN_KEY = "ACCESS_TOKEN";

    public static final String ACCESS_TOKEN_LOK_KEY = "ACCESS_TOKEN_LOK_KEY";

    public static final String JSAPI_TICKET = "JSAPI_TICKET";

    @Autowired
    private LockUtil lockUtil;

    /**
     * 获取AccessToen
     *
     * @return
     */
    public String getAccessToken() {
        try {
            String accessToken = redisUtils.get(ACCESS_TOKEN_KEY);
            if (StringUtils.isBlank(accessToken)) {
                if (lockUtil.getUntilHaveLock(ACCESS_TOKEN_LOK_KEY)) {
                    //没有去请求
                    accessToken = redisUtils.get(ACCESS_TOKEN_KEY);
                    if (StringUtils.isBlank(accessToken)) {
                        Map<String, Object> map = Jsapi_ticketUtil.getAccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET);
                        log.info("获取的AccessToken数据 ===== {}", map.toString());
                        accessToken = MapUtils.getString(map, "access_token");
                        //保存Redis
                        redisUtils.set(ACCESS_TOKEN_KEY, accessToken, (MapUtils.getLong(map, "expires_in")));
                    }
                }
            }
            return accessToken;
        } catch (Exception e) {
            log.error("获取AccessToken报错:{}", e);
            e.printStackTrace();
        } finally {
            lockUtil.unLock(ACCESS_TOKEN_LOK_KEY);
        }
        return null;
    }


    /**
     * 获取 Ticket
     *
     * @param url
     * @return
     */
    public Map<String, Object> getTicket(String url) {

        //其次就是 通过access_token获取jsapi_ticket
        String jsapiTicket = getJsapiTicket();
        if (StringUtils.isBlank(jsapiTicket)) {
            throw new TCException("获取签名失败");
        }
        log.info("jsapiTicket>>" + jsapiTicket);
        // 随机获取UUID
        String uuid = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
        log.info("uuid>>" + uuid);
        //获取时间戳
        long time = System.currentTimeMillis() / 1000;
        String timestamp = String.format("%010d", time);
        log.info("timestamp>>" + timestamp);
        String signature = Jsapi_ticketUtil.getSign(uuid, jsapiTicket, timestamp, url);
        log.info("signature>>" + signature);
        Map<String, Object> map = new HashMap<>(4);
        map.put("appId", WeChatConfig.APP_ID);
        map.put("timestamp", time);
        map.put("nonceStr", uuid);
        map.put("signature", signature);
        return map;
    }


    public String getJsapiTicket() {
        try {
            String accessToken = getAccessToken();
            String ticjet = redisUtils.get(JSAPI_TICKET);
            if (StringUtils.isBlank(ticjet)) {
                if (lockUtil.getUntilHaveLock(JSAPI_TICKET)) {
                    //没有去请求
                    ticjet = redisUtils.get(JSAPI_TICKET);
                    if (StringUtils.isBlank(ticjet)) {
                        JSONObject object = Jsapi_ticketUtil.getJsapiTicket(accessToken);
                        if (object == null || object.getInt("errcode") != 0) {
                            return null;
                        }
                        ticjet = object.getString("ticket");
                        //保存Redis
                        redisUtils.set(JSAPI_TICKET, ticjet, object.getLong("expires_in"));
                    }
                }
            }
            return ticjet;
        } catch (Exception e) {
            log.error("获取JsapiTicket报错:{}", e);
            e.printStackTrace();
        } finally {
            lockUtil.unLock(JSAPI_TICKET);
        }
        return null;
    }

}
